;/******************************************************************************
;/* @file start
;/* @brief  arm9 start code for armcc
;/* @date   2022-02-22
;/* @author kerndev@foxmail.com
;/*****************************************************************************/
Stack_Size       EQU     0x00000400
Heap_Size        EQU     0x00000000

	AREA STACK, NOINIT, READWRITE, ALIGN=3
SYS_Stack_Mem    SPACE   Stack_Size
SYS_Stack_Addr
SVC_Stack_Mem    SPACE   Stack_Size
SVC_Stack_Addr
IRQ_Stack_Mem    SPACE   Stack_Size
IRQ_Stack_Addr

	AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem         SPACE   Heap_Size
__heap_limit

;/*****************************************************************************/
; User Initial Stack & Heap
	AREA |.text|, CODE, READONLY
	IF      :DEF:__MICROLIB
	EXPORT  __initial_sp
	EXPORT  __heap_base
	EXPORT  __heap_limit
	ELSE
	IMPORT  __use_two_region_memory
	EXPORT  __user_initial_stackheap

__user_initial_stackheap PROC
	LDR     R0, = Heap_Mem
	LDR     R1, = (SYS_Stack_Mem + Stack_Size)
	LDR     R2, = (Heap_Mem +  Heap_Size)
	LDR     R3, = SYS_Stack_Mem
	BX      LR
	ENDP

	ENDIF     

;/*****************************************************************************/
; Vector_Table
	PRESERVE8
	AREA RESET, CODE, READONLY
Vector_Table
	B       Reset_Handler
	B       Reset_Handler ;UND
	B       SWI_Handler
	B       Reset_Handler ;ABT_PREFETCH
	B       Reset_Handler ;ABT_DATA
	B       Reset_Handler ;RSV
	B       IRQ_Handler
	B       FIQ_Handler

;/*****************************************************************************/
; Mode bits and interrupt flag (I&F) defines
CPSR_USR_MODE    EQU    0x10
CPSR_FIQ_MODE    EQU    0x11
CPSR_IRQ_MODE    EQU    0x12
CPSR_SVC_MODE    EQU    0x13
CPSR_ABT_MODE    EQU    0x17
CPSR_UND_MODE    EQU    0x1B
CPSR_SYS_MODE    EQU    0x1F
CPSR_I_BIT       EQU    0x80
CPSR_F_BIT       EQU    0x40

;/*****************************************************************************/
; Reset Handler
Reset_Handler PROC
	IMPORT  __main
	MSR     CPSR_c, #CPSR_SVC_MODE :OR: CPSR_I_BIT :OR: CPSR_F_BIT
	LDR     SP, =SVC_Stack_Addr
	MSR     CPSR_c, #CPSR_IRQ_MODE :OR: CPSR_I_BIT :OR: CPSR_F_BIT
	LDR     SP, =IRQ_Stack_Addr
	MSR     CPSR_c, #CPSR_SYS_MODE :OR: CPSR_I_BIT :OR: CPSR_F_BIT
	LDR     SP, =SYS_Stack_Addr

	;Setup Vector Table
	;MRC     p15, 0, R2, c1, c0, 0  ;Read CP15 to R2
	;ANDS    R2, R2, #(1 << 13)
	;LDREQ   R1, =0x00000000
	;LDRNE   R1, =0xFFFF0000
	;LDR     R0, =Vector_Table
	;LDMIA   R0!, {R2-R9}
	;STMIA   R1!, {R2-R9}
	
	LDR     R0, =__main
	BX      R0
	ENDP
	
;/*****************************************************************************/
; FIQ
FIQ_Handler PROC
	B       .
	ENDP

;/*****************************************************************************/
; IRQ Mode
; Hardware set CPSR_I_BIT
IRQ_Handler PROC
	IMPORT intc_handler
	SUB    LR, LR, #4
	STMFD  SP!, {R0-R12, LR}
	BL     intc_handler
	LDMFD  SP!, {R0-R12, PC}^
	ENDP

;/*****************************************************************************/
; SWI Mode
; Hardware set CPSR_I_BIT
SWI_Handler PROC
	IMPORT swi_handler
	STMFD  SP!, {R0-R12, LR}
	BL     swi_handler
	LDMFD  SP!, {R0-R12, PC}^
	ENDP
	
	END
